package com.myk.game.gobangchess;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.myk.game.gobangchess.beans.RoomConfigBean;
import com.myk.game.gobangchess.constants.AppConfig;
import com.myk.game.gobangchess.constants.Msger;
import com.myk.game.gobangchess.constants.PathCost;
import com.myk.game.gobangchess.constants.WinTag;
import com.myk.game.gobangchess.dates.AccountData;
import com.myk.game.gobangchess.dates.ChatData;
import com.myk.game.gobangchess.dates.NotificationData;
import com.myk.game.gobangchess.rooms.*;
import com.myk.game.gobangchess.utils.*;
//import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.*;

public class DataManager {

    //当前管理员
    public static Manager manager;
    //当前在线用户
    public static List<Player> playerList = new ArrayList<>();
    //当前开放的房间
    public static List<Room> roomList = new ArrayList<>();

    /**
     * 应用启动时加载所有本地数据
     */
    public static void loadAppData() {
        loadAccountData();
        loadRoomData();
        ChatData.loadPreMessageData();
        //cleanPlayingData();
    }

    //加载房间信息 //读取配置文件，校验格式，反射创建房间，若配置文件不存在那就按照下面的顺序先创建房间对象再创建配置文件
    public static void loadRoomData() {
        if (FileUtils.isFileExists(PathCost.ROOM_LIST_CONFIG_FILE)) {
            Gson gson = new Gson();
            try {
                String roomConfigJson = FileUtils.readFile2String(PathCost.ROOM_LIST_CONFIG_FILE);
                List<RoomConfigBean> roomConfigBeanList = gson.fromJson(roomConfigJson, new TypeToken<List<RoomConfigBean>>() {
                }.getType()); //从配置文件中获取已配置的房间列表
                List<RoomConfigBean> badConfigList = new ArrayList<>(); //已改名或者已经删除的类名
                roomList = new ArrayList<>();
                //反射创建房间列表对象
                for (RoomConfigBean roomConfigBeam : roomConfigBeanList) {
                    Class<?> roomClass = null;
                    try {
                        roomClass = Class.forName("com.myk.game.gobangchess.rooms" + "." + roomConfigBeam.getClassName());
                        Room room = (Room) roomClass.getConstructor(String.class).newInstance(roomConfigBeam.getRoomName());
                        room.setSaveHistoryToFile(roomConfigBeam.isSaveHistoryFile());
                        room.setCurRoomMode(roomConfigBeam.getMode());
                        room.setRoomIntroduce(roomConfigBeam.getIntroduce());
                        room.onCreatePrepare();
                        roomList.add(room); //添加到内存
                    }
                    catch (ClassNotFoundException e) {
                        badConfigList.add(roomConfigBeam); //添加到已改名或者已经删除的类名列表
                    }
                }
                //删除已改名或者已经删除的类名
                if (badConfigList.size() > 0) {
                    for (RoomConfigBean roomConfigBeam : badConfigList) {
                        System.out.println("已删除房间配置文件中：" + roomConfigBeam.getClassName());
                        roomConfigBeanList.remove(roomConfigBeam);
                    }
                    String roomConfigJsonNew = gson.toJson(roomConfigBeanList);
                    FileUtils.writeFileFromString(PathCost.ROOM_LIST_CONFIG_FILE, roomConfigJsonNew);
                }
            }
            catch (Exception e) {
                e.printStackTrace();
                System.out.println("读取房间配置文件失败，已自动从代码预设中创建房间列表");
                loadPresetRoomData();
            }
        }
        else {
            System.out.println("读取房间配置文件失败，已自动从代码预设中创建房间列表");
            loadPresetRoomData();
        }
    }

    //加载预设的房间列表数据，从配置文件里加载失败了就从这里加载并且更新配置文件，这里始终添加所有的已开发的房间
    public static void loadPresetRoomData() {
        roomList = new ArrayList<>();
        roomList.add(new FreeQuickRoom("~自由便捷画板~")); //至少得有一个房间
        updateRoomListConfigFile();
    }

    //更新房间列表配置文件
    public static void updateRoomListConfigFile() {
        List<RoomConfigBean> roomConfigBeanList = new ArrayList<>();
        for (Room room : roomList) {
            RoomConfigBean roomConfigBean = new RoomConfigBean();
            roomConfigBean.setClassName(room.getClass().getSimpleName());
            roomConfigBean.setChessName(room.getChessName());
            roomConfigBean.setRoomName(room.getRoomName());
            roomConfigBean.setSaveHistoryFile(room.isSaveHistoryToFile());
            roomConfigBean.setMode(room.getCurMode());
            roomConfigBean.setIntroduce(room.getRoomIntroduce());
            roomConfigBeanList.add(roomConfigBean);
        }
        Gson gson = new Gson();
        String json = gson.toJson(roomConfigBeanList);
        FileUtils.createOrExistsFile(PathCost.ROOM_LIST_CONFIG_FILE);
        FileUtils.writeFileFromString(PathCost.ROOM_LIST_CONFIG_FILE, json);
    }

    //从旧版本本地文件”账号配置文件“加载所有账户信息
    private static void loadAccountData() {
        String path = PathCost.DATA_ACCOUNT_FILE;
        File file = new File(path);
        if (file.isFile() && file.exists()) {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(file.toPath()), "gbk"));
                String str; //从txt中读取到的所有数据
                //所有账户信息
                List<Account> accountList = new ArrayList<>();
                //每一行是一条记录，每一条记录生成一个对象放到集合中
                while ((str = br.readLine()) != null) {
                    if (!str.trim().isEmpty()) { //排除空行的情况
                        //每一条记录映射成键值对的Map集合
                        Map<String, String> itemMap = dataStr2Map(str);
                        //具体的属性赋值在Account的构造函数内分配，之后就只需要更改Account一个类就行了
                        accountList.add(new Account(itemMap));
                    }
                }
                accountList.remove(0); //移除掉无用的第一条（暂时这样作，主要是为了应对windows自带txt文本的bug）
                br.close();

                //迁移数据
                String accountsPath = PathCost.DATA_ACCOUNT_GROUP_DIR;
                FileUtils.createOrExistsDir(accountsPath); //创建新的账户文件夹
                List<File> accountDirList = FileUtils.listFilesInDir(accountsPath);
                if (accountDirList.size() < accountList.size()) { //新账户文件夹数量少于旧的配置账户数量时
                    for (Account account : accountList) {
                        if (StringUtils.isSpace(account.getCreateTime())) {
                            account.setCreateTime("2023-03-29");
                        }
                        AccountData.managerCreateAccount(account.getIdCode(), account.getNickName(), account.getCreateTime());
                    }
                    FileUtils.delete(file); //迁移完以后删除数据
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //正确格式的字符串数据解析成Map集合
    private static Map<String, String> dataStr2Map(String dataStr) {
        Map<String, String> itemMap = new HashMap<>();
        String[] items = dataStr.split("&");
        for (String item : items) {
            String[] s = item.split(":");
            itemMap.put(s[0], s[1]);
        }
        return itemMap;
    }

    /**
     * 获取玩家最新安装包信息
     */
    public static String getPlayerApkVersion() {
        String apkUrl = AppConfig.player_apk_file_uri;
        String versionName = AppConfig.player_apk_version_name;
        String updateContent = AppConfig.player_apk_update_content;
        return "apkUrl:" + apkUrl +
                "&versionName:" + versionName +
                "&updateContent:" + updateContent;
    }

    //玩家登陆,添加新玩家到在线列表中，并且通知其它玩家
    public static synchronized void playerLogin(Player newPlayer) {
        playerList.add(newPlayer); //添加新玩家到在线列表
        newPlayer.updateLoginTime();//更新最近登录时间
        newPlayer.onLoginSuccess(); //新玩家初始化
        noticeOthersLogin(newPlayer); //通知其它玩家
        System.out.println(newPlayer.getNickNameOrTemp() + "登录成功");
        logAllPlayers();
    }

    //玩家退出,从在线列表中移除玩家，并通知其它玩家
    public static synchronized void playerLogout(Player player) {
        player.leaveRoom(); //玩家离开房间，也是房间移除玩家
        playerList.remove(player); //直接从在线列表中移除，不用返回消息给客户端
        noticeOthersLogout(player); //通知其它玩家有个玩家下线
        System.out.println("玩家" + player.getNickNameOrTemp() + "下线");
        logAllPlayers();
    }

    /**
     * 若该玩家在线返回玩家对象
     */
    public static Player getOnlinePlayerById(String idCode) {
        for (Player player : playerList) {
            if (player.getIdCode().equals(idCode)) {
                return player;
            }
        }
        return null;
    }

    /**
     * 管理员登录
     */
    public static synchronized void managerLogin(Manager manager) {
        if (DataManager.manager != null) {
            DataManager.manager.recycle();
        }
        DataManager.manager = manager;
        manager.onLoginSuccess();
        System.out.println("管理员登录成功");
    }

    /**
     * 管理员退出
     */
    public static synchronized void managerLogout(Manager manager) {
        DataManager.manager = null;
        System.out.println("管理员退出登录");
    }

    //通知所有其它玩家有新玩家登陆
    private static void noticeOthersLogin(Player player) {
        for (Player o : playerList) {
            if (!player.getIdCode().equals(o.getIdCode())) {
                o.sendMessage(Msger.otherLogin, player.getNickNameOrTemp());
                o.sendMessage(Msger.refreshPlayerListSum, AccountData.todayLoginPlayersCountCache + "&" + getPlayerListSum());
            }
        }
    }

    //通知所有玩家有玩家退出
    private static void noticeOthersLogout(Player player) {
        for (Player o : playerList) {
            if (!player.getIdCode().equals(o.getIdCode())) {
                o.sendMessage(Msger.otherLogout, player.getNickNameOrTemp());
                o.sendMessage(Msger.refreshPlayerListSum, AccountData.todayLoginPlayersCountCache + "&" + getPlayerListSum());
            }
        }
    }

    //打印所有当前在线的玩家
    private static void logAllPlayers() {
        System.out.println("在线玩家" + playerList.size() + "人");
        System.out.print("分别是：");
        for (Player player : playerList) {
            System.out.print(player.getNickNameOrTemp() + " ");
        }
        System.out.println();
    }

    /**
     * 获取管理员登录账号
     */
    public static boolean checkManager(String idCode) {
        if (idCode == null || idCode.isEmpty()) {
            return false;
        }
        else if (AppConfig.managerIdCode == null || AppConfig.managerIdCode.isEmpty()) {
            return false;
        }
        else {
            return AppConfig.managerIdCode.equals(idCode);
        }
    }

    /**
     * 打印当前房间列表
     */
    public static void printRoomList() {
        System.out.print("已配置房间：");
        for (Room room : DataManager.roomList) {
            System.out.print(room.getRoomName() + "  ");
        }
        System.out.println();
    }

    //获取大厅的房间数据，包含房间名称和房间里玩家的数量
    public static String getRoomListInfo() {
        List<Room> sortRoomList = new ArrayList<>(roomList);
        StringBuilder sb = new StringBuilder();
        for (Room room : sortRoomList) {
            sb.append(room.getHallRoomInfo()).append(";");
        }
        String s = sb.toString();
        if (s.isEmpty()) {
            return "-1";
        }
        else {
            return s.substring(0, s.length() - 1);
        }
    }

    //获取所有在线的用户数据，包含用户昵称
    public static String getPlayerListInfo() {
        StringBuffer sb = new StringBuffer();
        for (Player player : playerList) {
            sb.append(player.getNickNameOrTemp()).append(";");
        }
        String s = sb.toString();
        if (s.isEmpty()) {
            return "-1";
        }
        else {
            return s.substring(0, s.length() - 1);
        }
    }

    //获取在线玩家的数量
    public static int getPlayerListSum() {
        return playerList.size();
    }

    /**
     * 根据房间名称获取房间对象
     */
    public static Room getRoomByName(String roomName) {
        for (Room r : roomList) {
            if (r.getRoomName().equals(roomName)) {
                return r;
            }
        }
        return null;
    }

    /**
     * 获取某房间该日战报（克隆的房间视为统一房间）
     */
    public static String getRoomTodayRecords(String roomName, String todayDate) {
        Room room = getRoomByName(roomName);
        if (room != null) {
            String dirPath = PathCost.RECORDS_DIR + room.getClass().getSimpleName();
            if (FileUtils.isFileExists(dirPath)) {
                List<File> fileList = FileUtils.listFilesInDirWithFilter(dirPath, pathname -> pathname.getName().contains(todayDate));
                if (fileList.size() > 0) {
                    StringBuilder lists = new StringBuilder();
                    for (File file : fileList) {
                        lists.append("\n《");
                        lists.append(file.getName());
                        lists.append("》");
                        lists.append("\n------");
                    }
                    return "共" + fileList.size() + "条：" + lists;
                }
                else {
                    return "共0条";
                }
            }
            else {
                return "共0条";
            }
        }
        else {
            return "共0条";
        }
    }

    /**
     * 获取某房间该日战报（克隆的房间视为统一房间）
     */
    public static String getRoomDaysRecords(String roomName, String[] dates) {
        Room room = getRoomByName(roomName);
        if (room != null) {
            String dirPath = PathCost.RECORDS_DIR + room.getClass().getSimpleName();
            if (FileUtils.isFileExists(dirPath)) {
                List<File> fileList = FileUtils.listFilesInDirWithFilter(dirPath, pathname -> {
                    String name = pathname.getName();
                    for (String date : dates) if (name.contains(date)) return true;
                    return false;
                });
                if (fileList.size() > 0) {

                    //根据时间排序
                    fileList.sort((o1, o2) -> {
                        String name1 = o1.getName();
                        String name2 = o2.getName();
                        String time1 = name1.substring(name1.length()-18,name1.length()-4);
                        String time2 = name2.substring(name2.length()-18,name2.length()-4);
                        return time1.compareTo(time2);
                    });

                    //拼接数据
                    StringBuilder lists = new StringBuilder();
                    for (File file : fileList) {
                        lists.append("\n《");
                        lists.append(file.getName());
                        lists.append("》");
                        lists.append("\n------");
                    }
                    return "共" + fileList.size() + "条：" + lists;
                }
                else {
                    return "共0条";
                }
            }
            else {
                return "共0条";
            }
        }
        else {
            return "共0条";
        }
    }

    /**
     * 获取某房间的数据统计（克隆的房间视为同一房间）
     */
    public static String getRoomStatistics(String roomName, Account account) {
        Room room = getRoomByName(roomName);
        if (room != null) {
            String dirPath = PathCost.RECORDS_DIR + room.getClass().getSimpleName();
            if (FileUtils.isFileExists(dirPath)) {
                List<File> fileList = FileUtils.listFilesInDir(dirPath);
                if (fileList.size() > 0) {
                    LocalDateTime earliestTime = null;
                    LocalDateTime latestTime = null;
                    String latestBlackPlayer = null;
                    String latestWhitePlayer = null;
                    int blackWinCount = 0;
                    int whiteWinCount = 0;
                    int effectPlayedCount = 0; //有效对弈数统计
                    int effectStepCount = 0; //有效回合数统计
                    Map<String, Integer> playCountMap = new HashMap<>(); //玩家对弈次数统计
                    Map<String, Integer> winCountMap = new HashMap<>(); //玩家获胜次数统计
                    Map<String, Integer> scoreCountMap = new HashMap<>(); //玩家分数统计

                    for (File file : fileList) {
                        try {
                            /*文件格式形如   震棋_测试A(胜)_vs(35)_测试B(负)_20230928151246.txt   */
                            String fileName = file.getName();
                            fileName = fileName.substring(0, fileName.indexOf(".txt"));
                            String[] metaData = fileName.split("_");
                            /*最早统计时间*/
                            String timeStr = metaData[4];
                            LocalDateTime time = DateTimeUtil.strToLocalDateTime(timeStr, DateTimeUtil.ALLFORMAT);
                            if (earliestTime == null || DateTimeUtil.isBefore(time, earliestTime)) {
                                earliestTime = time;
                            }
                            if (latestTime == null || DateTimeUtil.isAfter(time, latestTime)) {
                                latestTime = time;
                                latestBlackPlayer = metaData[1].substring(0, metaData[1].indexOf("("));
                                latestWhitePlayer = metaData[3].substring(0, metaData[3].indexOf("("));
                            }
                            /*有效对弈数*/
                            boolean isEffectPlayed = true; //是否有效对弈，出现 认输，求和，离开的对局都不算完整有效的对弈。完整有效的对弈用于计算平均回合数的，不管是否有效都会进行计分
                            int fileStep = 0;//战报文件记录的回合数
                            if (metaData[2].length() > 2) { //"vs"长度为2，metaData长度大于二说明vs后面跟着回合数数据
                                fileStep = Integer.parseInt(metaData[2].substring(metaData[2].indexOf("(") + 1, metaData[2].indexOf(")")));
                            }
                            else {
                                isEffectPlayed = false;
                            }

                            /*获取对弈玩家昵称和胜负数据*/
                            String blackName = metaData[1].substring(0, metaData[1].indexOf("("));
                            String blackTag = metaData[1].substring(metaData[1].indexOf("("));
                            String whiteName = metaData[3].substring(0, metaData[3].indexOf("("));
                            String whiteTag = metaData[3].substring(metaData[3].indexOf("("));
                            int scoreS = Integer.parseInt(AppConfig.rank_s_get_score);
                            int scoreP = Integer.parseInt(AppConfig.rank_p_get_score);
                            int scoreF = Integer.parseInt(AppConfig.rank_f_get_score);
                            int scoreR = Integer.parseInt(AppConfig.rank_r_get_score);
                            int scoreL = Integer.parseInt(AppConfig.rank_l_get_score);

                            if (WinTag.S.equals(blackTag)) {
                                blackWinCount++;
                                int opc = playCountMap.getOrDefault(blackName, 0);
                                int npc = opc + 1;
                                playCountMap.put(blackName, npc);
                                int owc = winCountMap.getOrDefault(blackName, 0);
                                int nwc = owc + 1;
                                winCountMap.put(blackName, nwc);
                                int osc = scoreCountMap.getOrDefault(blackName, 0);
                                int nsc = osc + scoreS;
                                scoreCountMap.put(blackName, nsc);
                            }
                            else if (WinTag.P.equals(blackTag)) {
                                int opc = playCountMap.getOrDefault(blackName, 0);
                                int npc = opc + 1;
                                playCountMap.put(blackName, npc);
                                int osc = scoreCountMap.getOrDefault(blackName, 0);
                                int nsc = osc + scoreP;
                                scoreCountMap.put(blackName, nsc);
                            }
                            else if (WinTag.F.equals(blackTag)) {
                                int opc = playCountMap.getOrDefault(blackName, 0);
                                int npc = opc + 1;
                                playCountMap.put(blackName, npc);
                                int osc = scoreCountMap.getOrDefault(blackName, 0);
                                int nsc = osc + scoreF;
                                scoreCountMap.put(blackName, nsc);
                            }
                            else if (WinTag.R.equals(blackTag) || "(认输)".equals(blackTag)) {
                                int opc = playCountMap.getOrDefault(blackName, 0);
                                int npc = opc + 1;
                                playCountMap.put(blackName, npc);
                                int osc = scoreCountMap.getOrDefault(blackName, 0);
                                int nsc = osc + scoreR;
                                scoreCountMap.put(blackName, nsc);
                            }
                            else if (WinTag.L.equals(blackTag) || "(离开)".equals(blackTag)) {
                                isEffectPlayed = false;
                                int opc = playCountMap.getOrDefault(blackName, 0);
                                int npc = opc + 1;
                                playCountMap.put(blackName, npc);
                                int osc = scoreCountMap.getOrDefault(blackName, 0);
                                int nsc = osc + scoreL;
                                scoreCountMap.put(blackName, nsc);
                            }

                            if (WinTag.S.equals(whiteTag)) {
                                whiteWinCount++;
                                int opc = playCountMap.getOrDefault(whiteName, 0);
                                int npc = opc + 1;
                                playCountMap.put(whiteName, npc);
                                int owc = winCountMap.getOrDefault(whiteName, 0);
                                int nwc = owc + 1;
                                winCountMap.put(whiteName, nwc);
                                int osc = scoreCountMap.getOrDefault(whiteName, 0);
                                int nsc = osc + scoreS;
                                scoreCountMap.put(whiteName, nsc);
                            }
                            else if (WinTag.P.equals(whiteTag)) {
                                int opc = playCountMap.getOrDefault(whiteName, 0);
                                int npc = opc + 1;
                                playCountMap.put(whiteName, npc);
                                int osc = scoreCountMap.getOrDefault(whiteName, 0);
                                int nsc = osc + scoreP;
                                scoreCountMap.put(whiteName, nsc);
                            }
                            else if (WinTag.F.equals(whiteTag)) {
                                int opc = playCountMap.getOrDefault(whiteName, 0);
                                int npc = opc + 1;
                                playCountMap.put(whiteName, npc);
                                int osc = scoreCountMap.getOrDefault(whiteName, 0);
                                int nsc = osc + scoreF;
                                scoreCountMap.put(whiteName, nsc);
                            }
                            else if (WinTag.R.equals(whiteTag) || "(认输)".equals(blackTag)) {
                                int opc = playCountMap.getOrDefault(whiteName, 0);
                                int npc = opc + 1;
                                playCountMap.put(whiteName, npc);
                                int osc = scoreCountMap.getOrDefault(whiteName, 0);
                                int nsc = osc + scoreR;
                                scoreCountMap.put(whiteName, nsc);
                            }
                            else if (WinTag.L.equals(whiteTag) || "(离开)".equals(blackTag)) {
                                isEffectPlayed = false;
                                int opc = playCountMap.getOrDefault(whiteName, 0);
                                int npc = opc + 1;
                                playCountMap.put(whiteName, npc);
                                int osc = scoreCountMap.getOrDefault(whiteName, 0);
                                int nsc = osc + scoreL;
                                scoreCountMap.put(whiteName, nsc);
                            }

                            /*完整有效对弈数和回合数统计*/
                            if (isEffectPlayed) {
                                effectPlayedCount += 1;
                                effectStepCount += fileStep;
                            }
                        }
                        catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        /*对分数统计进行升序排序*/
                        List<Map.Entry<String, Integer>> scoreMapEntryList = new ArrayList<>(scoreCountMap.entrySet());
                        scoreMapEntryList.sort(Map.Entry.comparingByValue());
                        int youIndex = -1;
                        int topCount = Integer.parseInt(AppConfig.rank_player_on_top_count);
                        List<String> top10List = new ArrayList<>(topCount);
                        for (int i = scoreMapEntryList.size() - 1; i >= 0; i--) {
                            if (scoreMapEntryList.get(i).getKey().equals(account.getNickName())) {
                                youIndex = i;
                            }
                            if (top10List.size() < topCount) {
                                top10List.add(scoreMapEntryList.get(i).getKey());
                            }
                        }

                        String earliestTimeStr = DateTimeUtil.localDateTimeToStr(earliestTime, DateTimeUtil.DATE_FORMAT);
                        int allPlayerCount = playCountMap.size();
                        int allPlayingCount = fileList.size();
                        int yourRank = allPlayerCount - youIndex;
                        int youPlayingCount = playCountMap.getOrDefault(account.getNickName(), 0);
                        int youWinCount = winCountMap.getOrDefault(account.getNickName(), 0);
                        int youScore = scoreCountMap.getOrDefault(account.getNickName(), 0);

                        StringBuilder statisticsInfo = new StringBuilder("《" + room.getChessName() + "》\n");
                        statisticsInfo.append("数据统计自").append(earliestTimeStr).append("起。\n");
                        statisticsInfo.append("有效对弈").append(allPlayerCount).append("人").append(allPlayingCount).append("场");
                        if (effectPlayedCount > 0) {
                            int average = (int) (effectStepCount * 1.0f / effectPlayedCount);
                            statisticsInfo.append("，平均每局").append(average).append("步");
                        }
                        statisticsInfo.append("。\n");
                        statisticsInfo.append("目前执黑胜").append(blackWinCount).append("场，执白胜").append(whiteWinCount).append("场。\n");
                        String latestTimeStr = DateTimeUtil.localDateTimeToStr(latestTime, DateTimeUtil.DATE_FORMAT);
                        statisticsInfo.append("最近一场对弈时间是").append(latestTimeStr).append("。\n")
                                .append("最近对弈的玩家是").append("(黑)").append(latestBlackPlayer).append("(白)").append(latestWhitePlayer).append("。\n");
                        statisticsInfo.append("【排行榜】");
                        if (youIndex != -1) {
                            String youInfo = "\n您排第" + yourRank + "名，对弈" + youPlayingCount + "场，获胜" + youWinCount + "次，总计" + youScore + "分。";
                            statisticsInfo.append(youInfo);
                        }
                        for (int i = 0; i < top10List.size(); i++) {
                            int rank = i + 1;
                            String name = top10List.get(i);
                            int playing = playCountMap.getOrDefault(name, 0);
                            int win = winCountMap.getOrDefault(name, 0);
                            int score = scoreCountMap.getOrDefault(name, 0);
                            String itemStr = "\n[第" + rank + "名]" + name + "(对弈" + playing + "场，获胜" + win + "次，总计" + score + "分)";
                            statisticsInfo.append(itemStr);
                        }
                        return statisticsInfo.toString();
                    }
                    catch (Exception e) {
                        return "统计信息出现异常请联系管理员";
                    }
                }
                else {
                    return "暂无统计信息。。。";
                }
            }
            else {
                return "暂无统计信息。。。";
            }
        }
        else {
            return "暂无统计信息。。。";
        }
    }

    /**
     * 获取某个房间的战报总数
     */
    public static int getRoomRecordsCount(Room room) {
        String dirPath = PathCost.RECORDS_DIR + room.getClass().getSimpleName();
        if (FileUtils.isFileExists(dirPath)) {
            List<File> fileList = FileUtils.listFilesInDir(dirPath);
            return fileList.size();
        }
        else {
            return 0;
        }
    }

    /**
     * 通知所有玩家更新RoomList信息
     */
    public static void noticeAllRefreshRoomList() {
        String value = getRoomListInfo();
        for (Player player : playerList) {
            if (player.getEnteringRoom() == null) { //不在房间，在大厅的玩家才刷新房间列表数据
                player.sendMessage(Msger.refreshRoomList, value);
            }
        }
    }

    /**
     * 通知所有人有个游戏开始了
     */
    public static void noticeAllGameStart(Player player_black, Player player_white, String roomName) {
        for (Player player : playerList) {
            player.sendMessage(Msger.gameStart, player_black.getNickNameOrTemp() + " 和 " + player_white.getNickNameOrTemp() + " 在 " + roomName + " 开始对弈");
        }
    }

    /**
     * 给所有在线用户发消息
     */
    public static void noticeAllBroadcast(String msg) {
        for (Player player : playerList) {
            player.sendMessage(Msger.broadcast, msg);
        }
    }

    /**
     * 给所有在线用户发弹窗消息
     */
    public static void sendAllInfoDialog(String info) {
        for (Player player : playerList) {
            player.sendMessage(Msger.showInfoDialog, info);
        }
    }

    /**
     * 在线用户全部立即受到公告通知
     */
    public static void noticeAllNotification() {
        String notificationIds = NotificationData.getActiveNotificationIds(); //获取所有活跃的公告的id
        if (!notificationIds.equals("-1")) {
            for (Player player : playerList) {
                player.sendMessage(Msger.pushNotificationIds, notificationIds);
            }
        }
    }

    /**
     * 获取系统资源占用信息
     */
    public static String getSystemInfo() {
        return "暂未找的合适的方式实现";
    }

    /**
     * 获取内存占用信息 （用在开发环境验证，在服务器环境下执行会报错，因为高版本移除了jdk的nashorn.jar依赖）
     */
    /*public static String getMemoryUsage() {
        System.setProperty("java.vm.name", "Java HotSpot(TM) ");
        StringBuilder data = new StringBuilder("[内存占用数据]\n");
        try {
            MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
            MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
            long usedHeapMemory = heapMemoryUsage.getUsed();
            String usedHeap = StringUtils.assignSize(usedHeapMemory);
            data.append("已使用堆内存:").append(usedHeap).append("\n");
            long maxHeapMemory = heapMemoryUsage.getMax();
            String maxHeap = StringUtils.assignSize(maxHeapMemory);
            data.append("最大堆内存:").append(maxHeap).append("\n");
            double heapMemoryUsagePercentage = ((double) usedHeapMemory / maxHeapMemory) * 100.0;
            String percent = heapMemoryUsagePercentage + "%";
            data.append("内存占用比:").append(percent).append("\n");
        }
        catch (Exception e) {
            data.append("发生异常\n");
        }
        data.append("[房间对象大小]\n");
        try {
            for (Room room : roomList) {
                String name = room.roomName;
                //String size = StringUtils.assignSize(ObjectSizeCalculator.getObjectSize(room));
                data.append(name).append(":").append(size).append("\n");
            }
        }
        catch (UnsupportedOperationException e) {
            data.append("发生异常\n");
        }
        data.append("[用户对象大小]\n");
        try {
            for (Player player : playerList) {
                String name = player.getNickNameOrTemp();
                //String size = StringUtils.assignSize(ObjectSizeCalculator.getObjectSize(player));
                data.append(name).append(":").append(size).append("\n");
            }
        }
        catch (UnsupportedOperationException e) {
            data.append("发生异常\n");
        }
        return data.toString();
    }

    //测试
    public static void main(String[] args) {
       /* LocalDateTime localDateTime = LocalDateTime.now();
        String formatTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd-HH/mm/ss"));
        //LocalDateTime localDateTime1 = LocalDateTime.parse(formatTime,DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"));
        System.out.println(formatTime);

        //LocalDateTime time = DateTimeUtil.strToLocalDateTime("20000317123456",DateTimeUtil.ALL_FORMAT);
        //LocalDateTime time2 = DateTimeUtil.strToLocalDateTime("20000317123456",DateTimeUtil.ALLFORMAT);
        //System.out.println(time);
        //System.out.println(time);


    }*/

}
